{
    function f() {
        console.log('hi!')
    }

    // f()
    f();  // 行尾必须加分号？
    (f)()
    new f()

    // Indirect Invocation
    // f.invoke()  // 不能用 invoke(), 未定义此种调用方式
    f.call()
    f.apply()
}

{ // `call()` 和 `apply()` 真正的作用是将对象作为参数传递给第三方函数
    class Hi {
        name = 'Google'

        constructor(name) {
            this.name = name
        }
    }

    function f1() {
        console.log(`Hi ${this.name}!`)
    }

    const hi = new Hi()
    f1.call(hi)
    f1.apply(Hi)
    f1.apply(hi)

    hi.m = f1
    hi.m()

    function f2(x, y) {
        console.log(`${this.name}: ${x} + ${y} = ${x + y}!`)
    }

    f2.call(new Hi('Sum'), 2, 3)
    f2.apply(new Hi('Sum'), [2, 3])
}